<?php
declare (strict_types = 1);

namespace App\Service\Rbac;

use App\Constants\DefaultValue;
use App\Constants\ErrorCode;
use App\Constants\RedisKey;
use App\Dao\AuthCompanyDao;
use App\Dao\AuthEmployeeDao;
use App\Dao\AuthOrganizationDao;
use App\Dao\AuthPermissionDao;
use App\Exception\BusinessException;
use App\Lib\JwtToken;use App\Utils\ApiUtils;
use Gregwar\Captcha\CaptchaBuilder;
use Gregwar\Captcha\PhraseBuilder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;

class LoginService
{
    /**
     * @Inject
     * @var AuthEmployeeDao
     */
    protected $authEmployeeDao;
    protected $redis;
    public function __construct()
    {
        $container = ApplicationContext::getContainer();
        $this->redis = $container->get(Redis::class);
    }

    public function account(array $data)
    {
        // 识别是否是验证过授权码的
        $this->checkAuth($data['key'], $data['content']);
        // 验证公司名称是否存在
        $hasCompany = make(AuthCompanyDao::class)->firstByWhereTrait(
            ['name' => $data['company'],
                'is_del' => 1]);
        if ($hasCompany) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '公司名称已存在');
        }

        // 验证账号是否存在
        if (make(AuthEmployeeDao::class)->existsByWhereTrait(['account' => $data['account']])) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '该账号系统已存在');
        }
        Db::beginTransaction();
        try {
            $new_company = make(AuthCompanyDao::class)->insertGetIdTrait(
                ['name' => $data['company'],
                    'verification' => $data['verification'],
                    'add_time' => time()]);
            $organization = make(AuthOrganizationDao::class)->createTrait([
                'name' => $data['company'],
                'prefix_name' => $data['company'] . '-',
                'company_id' => $new_company,
                'pid' => 0,
                'add_time' => time()]);
            $account = ['job_number' => $data['account'],
                'account' => $data['account'],
                'organization_id' => $organization->id,
                'password' => ApiUtils::aesEnPassword($data['password']),
                'phone' => $data['phone'],
            ];
            $account = make(AuthEmployeeDao::class)->createTrait($account);
            make(AuthOrganizationDao::class)->updateByWhereTrait(['id' => $organization->id], ['employee_id' => $account->id]);
            Db::commit();
            return $data;
        } catch (\Throwable $t) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '网络异常 数据写入失败' . $t->getMessage());
        }
    }

    public function auth(string $verfication)
    {
        // to do 校验授权码是否正确
        if ($verfication != 'hellokitty') {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '授权码不正确');
        } else {
            //把授权校验码存redis
            mt_srand();
            $key = time() . mt_rand(1, 1000000);
            $content = ApiUtils::encryption($key);
            $this->redis->setex(RedisKey::AUTH_CODE_KEY . $key, DefaultValue::AUTH_ACCOUNT_TTL, $content);
            return ['key' => $key, 'content' => $content];
        }
    }

    public function login(array $request): array
    {
        $this->checkCapcha($request['key'], (int) $request['code']);
        $info = $this->authEmployeeDao->firstByWhereTrait(['account' => $request['name'], 'is_del' => 1]);
        if (empty($info)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '用户名错误');
        }
        if ($info->admin_status != 1) throw  new BusinessException(ErrorCode::ERR_BUESSUS, '该账户不能登录后台');
        if (ApiUtils::aesEnPassword($request['password']) == $info->password) {
            $this->authEmployeeDao->updateByWhereTrait(['id' => $info->id], ['update_time' => time()]);
            $token = JwtToken::authorizations([
                'id' => $info->id,
                'name' => $info->name,
                'account' => $info->account,
                'company_id' => $info->company_id],
                config('web.admin_jwt_key'));
            $menu = make(AuthPermissionDao::class)->searchPerByWhereId((int) $info->id);
            return ['user_id' => $info->id,
                'account' => $info->account,
                'token' => $token['token'],
                'refresh_token' => $token['refresh_token'],
                'menu' => $menu];
        }
        throw new BusinessException(ErrorCode::ERR_BUESSUS, '密码错误');
    }

    // 生成验证码
    public function verify(): array
    {
        // 创建4位的字符串验证码
        $phraseBuilder = new PhraseBuilder(4, '0123456789');
        //创建验证码图片
        $builder = new CaptchaBuilder(null, $phraseBuilder);
        $builder->build(150, 40);
        //把验证码存redis
        mt_srand();
        $key = time() . mt_rand(1, 1000000);
        $this->redis->setex(
            RedisKey::VERIFY_CODE_IMG . $key,
            DefaultValue::IMAGE_CAPTCHA_TTL,
            $builder->getPhrase());
        return ['key' => $key, 'content' => $builder->inline()];
    }

    // 校验验证码
    public function checkCapcha(string $key, int $code): bool
    {
        if (config('web.active_capcha')) {
            return true;
        }

        $scode = $this->redis->get(RedisKey::VERIFY_CODE_IMG . $key);
        $this->redis->del(RedisKey::VERIFY_CODE_IMG . $key);
        if (!$code || !$scode) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '验证码不存在');
        }

        if ($code != $scode) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '验证码不对');
        }

        return true;
    }

    // 授权码检测
    public function checkAuth(string $key, string $content): bool
    {
        $scode = $this->redis->get(RedisKey::AUTH_CODE_KEY . $key);
        $this->redis->del(RedisKey::AUTH_CODE_KEY . $key);
        if (!$content || !$scode) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '授权状态不存在');
        }

        if ($content != $scode) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '授权状态错误');
        }

        return true;
    }

    // 刷新token数据
    public function refreshToken($header, array $change_info = [])
    {
        return JwtToken::refreshToken($header[0] ?? '', config('web.admin_jwt_key'), $change_info);
    }
}
